<?php
declare (strict_types=1);

namespace app\common\builder;

use app\common\model\Account;
use think\App;
use think\Response;
use think\Validate;
use think\facade\Event;
use think\facade\View;
use think\response\Json;
use think\exception\ValidateException;
use think\exception\HttpResponseException;

abstract class TableBase
{

    /**
     * Request实例
     * @var \think\Request
     */
    protected $request;

    /**
     * 应用实例
     * @var \think\App
     */
    protected $app;

    /**
     * 搜索
     * @var \think\App
     */
    protected $search;

    /**
     * 是否批量验证
     * @var bool
     */
    protected $batchValidate = false;

    /**
     * 系统参数
     * @var array
     */
    protected $system;

    /**
     * 管理员信息
     * @var object
     */
    protected $admin;

    public function __construct(App $app)
    {
        $this->app = $app;
        $this->request = $this->app->request;

        // 控制器初始化
        $this->initialize();

    }

    public function initialize()
    {
        $this->admin = $this->request->admin;
        View::assign([
            'nav'    => $this->request->nav,
            '_admin' => $this->admin,
            'action' => $this->request->action,
        ]);
    }

    public function setMap($name = '')
    {
        $map = [];
        $like = [];
        $time = [];
        $param = $this->request->get();

        /**
         * 原点 2021年8月10日16:28:58 extraSearch变量解释说明
         * array格式，额外查询条件，如单个页面需要根据传参不同而获取不同数据，如不需要，无需定义此变量
         */

        if (isset($this->extraSearch) && $this->extraSearch) {
            foreach ($this->extraSearch as $v) {
                if (isset($param[$v]) && $param[$v]) {
                    $map[$v] = $param[$v];
                }
            }
        }

        /**
         * 原点 2022年2月23日14:15:25 extraMap变量解释说明
         * array格式，额外初始查询条件
         */
        $extraMap = TableFront::getInstance()->getExtraMap($name);
        if ($extraMap) {
            foreach ($extraMap as $k => $v) {
                $map[$k] = $v;
            }
        }

        $pool_id = 0;
        if($name == 'Account_bonus' && isset($map['pool_id'])){
            $pool_id = $map['pool_id'];
            unset($map['pool_id']);
        }

        if ($pool_id && in_array($pool_id, [1, 2, 3, 4, 5, 6, 7, 8])) {
            if (6 == $pool_id) {
                $category = Account::CONSUM_SHARE_LEADER;
            } elseif (7 == $pool_id) {
                $category = Account::CONSUM_SHARE_DISTRICT;
            } elseif (8 == $pool_id) {
                $category = Account::CONSUM_SHARE_CITY;
            } else {
                $category = Account::CONSUM_SHARE_SHOPER;
            }
            //$that = $that->where('category', $category);
            $map['category'] = $category;
        }

        /**
         * 原点  2021年8月10日16:28:17 search变量解释说明
         * 第1个参数为：要搜索的字段，如有多字段请双下划线拼接，例如：user__mobile__code 则代表查询这3个字段
         * 第2个参数为：搜索框的标题显示
         * 第3个参数为：搜索类型的显示，如input/select
         * 第4个参数为：搜索框类型为select时，需要传的值，数组格式，其他情况需留空
         * 第5个参数为：关联表查询的Model类，需填写全部命名空间，如未关联查询，则需留空
         * 第6个参数为：关联表查询字段，一般为id，如未关联查询，则需留空
         * 第7个参数为：是否like查询，是的话传入like即可
         * 目前较为繁琐，逐步优化中.....
         */

        $search = TableFront::getInstance()->getSearch($name);
        if ($search && isset($param['is_search']) || isset($param['summary'])) {
            foreach ($search as $v) {
                switch ($v[2]) {
                    case "linkage":
                        $keyAll = explode(',', $v[0]);
                        foreach ($keyAll as $item) {
                            if (isset($param[$item]) && $param[$item]) {
                                $map[$item] = $param[$item];
                            }
                        }
                        break;
                    case "time":
                        $key = str_replace("__", "|", $v[0]);
                        $time[$key] = $param[$v[0]];
                        unset($param[$v[0]]);
                        break;
                    default:
                        if (isset($param[$v[0]]) && $param[$v[0]]) {
                            if (isset($v[4]) && $v[4]) {
                                $field = explode(',', $v[5]);
                                $ids = $v[4]::where($field[0], $param[$v[0]])->column($field[1]);
                                $map[$v[0]] = $ids;
                            } else {
                                $key = str_replace("__", "|", $v[0]);

                                if (isset($v[6]) && $v[6]) {
                                    $like[] = [$key => $param[$v[0]]];
                                } else {
                                    $map[$key] = $param[$v[0]];
                                }
                            }
                        }
                }

            }
        }
        $param['otherTimes'] = $time;
        return ['map' => $map, 'param' => $param, 'like' => $like, 'time' => $time];
    }

    /**
     * 原点 2021年7月27日17:22:29 获取相关数据
     */
    public function getList($takeOver = false): Json
    {
        $s = $this->setMap($this->request->get('name'));

        $hasOne = isset($this->hasOne) ? $this->hasOne : '';

        $append = isset($this->append) ? $this->append : [];

        $sort = isset($this->sort) ? $this->sort : 'create_time,desc';

        if ($takeOver) {
            $result = $this->model::_all($s['map'], $s['param'], $hasOne, $s['like'], $sort, $append);
        } else {
            $result = $this->model::all($s['map'], $s['param'], $hasOne, $s['like'], $sort, $append);
        }

        return json($result);
    }


    /**
     * 原点 2021年7月27日11:05:32 公共添加方法
     */
    public function add($name = '', $tpl = 'form/add')
    {
        try {
            if ($tpl == 'form/add') {
                View::assign('field', TableFront::getInstance()->getEditable($name, 'add'));
            }
            return View::fetch($tpl);

        } catch (\Exception $e) {
            return $e->getMessage();
        }
    }

    /**
     * 原点 2021年7月27日11:05:32 公共修改方法
     */
    public function edit($name = '', $id = '', $tpl = 'form/edit', $info = '')
    {
        try {
            if ($tpl == 'form/edit') {
                View::assign('field', TableFront::getInstance()->getEditable($name, 'edit'));
            }
            View::assign('info', $info ?: $this->model::where($this->pk, $id)->find());
            return View::fetch($tpl);

        } catch (\Exception $e) {
            return $e->getMessage();
        }
    }

    /**
     * @param array $param -- 新增或修改的数据，支持直接调用和间接调用
     * @param array $model -- 调用model方法，默认false
     *
     * 原点 2021年7月27日14:46:07 公共新增/修改方法
     */
    public function save($param = [], $model = false): Json
    {
        $param = empty($param) ? $this->request->post() : $param;
        if (!isset($param[$this->pk]) && isset($this->validate)) {
            try {

                $this->validate($param, $this->validate);
            } catch (ValidateException $e) {
                return json(['code' => -1, 'msg' => $e->getError()]);
            }

        }
        if ($model) {

            $result = $this->model::_save($param, $this->admin);
        } else {
            $result = $this->model::_magic($param, $this->admin);
        }

        return json($result);
    }

    /**
     * 原点 2021年7月27日14:46:29 公共修改字段方法
     */
    public function update($id, $key, $val): Json
    {
        try {

            $val = $val == 'true' ? 1 : $val;
            $val = $val == 'false' ? 0 : $val;
            if (is_array($id)) {
                $model = $this->model::update([$key => $val], [$this->pk => $id]);
                $model->operation = 'updateAll';
                $model->ids = $id;
            } else {
                $model = $this->model::find($id);
                $model->$key = $val;
                $model->save();
                $model->operation = 'update';
            }

            Event::trigger('Logs', $model);
            return json(['code' => 1, 'msg' => '操作成功']);

        } catch (\Exception $e) {
            return json(['code' => -1, 'msg' => $e->getMessage()]);
        }

    }

    /**
     * 原点 2021年7月27日14:46:29 公共删除方法
     */
    public function delete($key = 'is_del'): Json
    {
        try {
            $id = $this->request->post($this->pk);
            if (is_array($id)) {
                $model = $this->model::update([$key => 1], ['id' => $id]);
                $model->operation = 'deleteAll';
                $model->ids = $id;
            } else {
                $model = $this->model::where($this->pk, $id)->find();
                $model->$key = 1;
                $model->save();
                $model->operation = 'delete';
            }
            Event::trigger('Logs', $model);
            return json(['code' => 1, 'msg' => '操作成功']);

        } catch (\Exception $e) {
            return json(['code' => -1, 'msg' => $e->getMessage()]);
        }
    }


    /**
     * 验证数据
     * @access protected
     * @param array $data 数据
     * @param string|array $validate 验证器名或者验证规则数组
     * @param array $message 提示信息
     * @param bool $batch 是否批量验证
     * @return array|string|true
     * @throws ValidateException
     */
    protected function validate(array $data, $validate, array $message = [], bool $batch = false)
    {
        if (is_array($validate)) {
            $v = new Validate();
            $v->rule($validate);
        } else {
            if (strpos($validate, '.')) {
                // 支持场景
                [$validate, $scene] = explode('.', $validate);
            }
            $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
            $v = new $class();
            if (!empty($scene)) {
                $v->scene($scene);
            }
        }

        $v->message($message);

        // 是否批量验证
        if ($batch || $this->batchValidate) {
            $v->batch(true);
        }

        return $v->failException(true)->check($data);
    }

    protected function error($msg = '', string $url = null, $data = '', int $wait = 86400, array $header = []): Response
    {
        if (is_null($url)) {
            $url = request()->isAjax() ? '' : 'javascript:history.back(-1);';
        } elseif ($url) {
            $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : app('route')->buildUrl($url);
        }

        $result = [
            'code' => 0,
            'msg'  => $msg,
            'data' => $data,
            'url'  => $url,
            'wait' => $wait,
        ];

        $type = (request()->isJson() || request()->isAjax()) ? 'json' : 'html';

        // 所有form返回的都必须是json，所有A链接返回的都必须是Html
        $type = request()->isGet() ? 'html' : $type;

        if ($type == 'html') {
            $response = view((string)app('config')->get('app.dispatch_error_tmpl'), $result);
        } else if ($type == 'json') {
            $response = json($result);
        }

        throw new HttpResponseException($response);

    }

}
